package main

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"io/ioutil"
)

func main() {
	signature,err:=rsaSignData(`./privateRsaKey.pem`,[]byte("你好，王彦超。本轮测试内容为：知道了，下次一定。"))
	if err != nil {
		fmt.Println("4:",err)
		return
	}
	fmt.Println("签名内容为：",hex.EncodeToString(signature))

	err=rsaVerifyData(signature,`./publicRsaKey.pem`,[]byte("你好，王彦超。本轮测试内容为：知道了，下次一定1。"))
	if err != nil {
		fmt.Println("内容被修改：",err)
		return
	}
	fmt.Println("内容一致。")
}

/*
传入内容，私钥文件，然后根据私钥生成对内容的哈希值做签名
 */
func rsaSignData(privateKeyPath string,text []byte) ([]byte,error) {
	// 1.根据私钥文件地址读取内容
	info, err := ioutil.ReadFile(privateKeyPath)
	if err != nil {
		fmt.Println("1:",err)
		return nil,err
	}
	// 2.根据pem得到Block
	block, _ :=pem.Decode(info)
	// 3.根据bolck得到私钥密钥内容
	/*
	func ParsePKCS1PrivateKey
	func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
	ParsePKCS1PrivateKey解析ASN.1 PKCS#1 DER编码的rsa私钥。
	 */
	PrivateKey,err:=x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		fmt.Println("2:",err)
		return nil,err
	}
	/*
	给原文做hash
	 */
	hash:=sha256.Sum256(text)
	/*
	使用私钥进行签名
	func SignPKCS1v15
	func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error)
	SignPKCS1v15使用RSA PKCS#1 v1.5规定的RSASSA-PKCS1-V1_5-SIGN签名方案计算签名。注意hashed必须是使用提供给本函数的hash参数对（要签名的）原始数据进行hash的结果。
	 */
	signature,err:=rsa.SignPKCS1v15(rand.Reader,PrivateKey,crypto.SHA256,hash[:])
	if err != nil {
		fmt.Println("3:",err)
		return nil,err
	}
	fmt.Println("生成签名成功！")
	return signature,nil
}

/*
传入内容，签名内容，公钥文件，内容，然后根据公钥判断传输过程是否修改过
*/
func rsaVerifyData(rsaSign []byte,publicKeyPath string,text []byte) (error) {
	// 1.根据公钥文件地址读取内容
	info, err := ioutil.ReadFile(publicKeyPath)
	if err != nil {
		fmt.Println("1:",err)
		return err
	}
	// 2.根据pem得到Block
	block, _ :=pem.Decode(info)
	// 3.根据bolck得到公钥内容
	/*
		func ParsePKCS1PrivateKey
		func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
		ParsePKCS1PrivateKey解析ASN.1 PKCS#1 DER编码的rsa私钥。
	*/
	publicKey,err:=x509.ParsePKCS1PublicKey(block.Bytes)
	if err != nil {
		fmt.Println("2:",err)
		return err
	}
	/*
		给原文做hash
	*/
	hash:=sha256.Sum256(text)
	/*
	func VerifyPKCS1v15
	func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error)
	VerifyPKCS1v15认证RSA PKCS#1 v1.5签名。hashed是使用提供的hash参数对（要签名的）原始数据进行hash的结果。合法的签名会返回nil，否则表示签名不合法。
	 */

	err=rsa.VerifyPKCS1v15(publicKey,crypto.SHA256,hash[:],rsaSign)
	if err != nil {
		//fmt.Println("内容被修改：",err)
		return err
	}
	return nil
}